import { FC, ReactElement, ReactNode, UIEventHandler, useEffect, useLayoutEffect, useRef, useState } from 'react'
import { jieliuUtil } from '@/util/util'
import './VList.less'
import VListChildren from './VListChildren'
type TVlist = {
  children: ReactElement
  offset?: number
  callback?: Function
}
const VList: FC<TVlist> = ({ children, offset = 100, callback }) => {
  const [scrollTop, setScrollTop] = useState(0)
  const childDom = useRef<HTMLDivElement | null>(null)
  const vlistDom = useRef<HTMLDivElement | null>(null)
  const [outHeight, setOutHeight] = useState(0)
  // 在计算top的时候，当前的top = 上一个dom的top+上一个dom的height 由此得知最后计算出来的值同时也是滚动列表虚拟之前的最大高度
  const lastHeight = useRef<number>(0)
  const lastChildren = useRef<ReactElement[] | null>(null)
  const scrollData: UIEventHandler<HTMLDivElement> = e => {
    const scrollTop = e.currentTarget.scrollTop
    const domHeight = e.currentTarget.getBoundingClientRect().height
    setScrollTop(scrollTop)
    if (lastHeight.current < scrollTop + domHeight + offset) {
      callback && jieliuUtil(callback, offset)
    }
  }
  useLayoutEffect(() => {
    const { height } = vlistDom.current!.getBoundingClientRect()
    setOutHeight(height)
  }, [])
  useLayoutEffect(() => {
    const childrenList = children.props.children
    let needFresh = false
    if (lastChildren.current) {
      lastChildren.current.forEach((item, index) => {
        if (!childrenList[index] || item.key !== childrenList[index].key) {
          needFresh = true
        }
      })
    }
    needFresh && (lastHeight.current = 0)
    lastChildren.current = childrenList
    const childDomList = Array.from(childDom.current!.children)
    if (childDomList.length) {
      for (const childDomIndex in childDomList) {
        const childDomItem = childDomList[childDomIndex]
        if ((childDomItem as HTMLDivElement).style.top && !needFresh) {
          lastHeight.current = parseFloat((childDomItem as HTMLDivElement).style.top)
        } else {
          ;(childDomItem as HTMLDivElement).style.top = lastHeight.current + 'px'
        }
        const { height } = childDomItem.getBoundingClientRect()
        lastHeight.current = lastHeight.current + height
      }
    }
  }, [children])

  return (
    <div ref={vlistDom} className="vlist" onScroll={scrollData}>
      <div ref={childDom} className="vlist-content">
        {children &&
          children.props.children.map((item: any) => {
            return (
              <VListChildren outHeight={outHeight} key={item.key} scrollTop={scrollTop} offset={offset}>
                {item}
              </VListChildren>
            )
          })}
      </div>
    </div>
  )
}
export default VList
